﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.ComponentModel;

namespace System.Windows.JControls.JColorPicker.Tracker
{
    /// <summary>
    /// The base-class from a Trackercontrol.
    /// </summary>
    public abstract class ColorTracker : Control
    {
        /// <summary>
        /// Event, when the value is changing.
        /// </summary>
        public event EventHandler ValueChanged;

        private double _value;
        private double _minValue;
        private double _maxValue;

        /// <summary>
        /// Initialze the class.
        /// </summary>
        public ColorTracker()
            : base()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
            Padding = new System.Windows.Forms.Padding(6, 2, 6, 3);
        }

        /// <summary>
        /// Setting the values for the tracker.
        /// </summary>
        /// <param name="minValue">The minimal value.</param>
        /// <param name="maxValue">The maximal value</param>
        /// <param name="value">The selected value.</param>
        protected void SetValue(int minValue, int maxValue, int value)
        {
            _minValue = minValue;
            _maxValue = maxValue;
            _value = value;
        }

        /// <summary>
        /// Get or set the selected value. After setting the control will be invalidated.
        /// </summary>
        public double Value
        {
            get { return _value; }
            set
            {
                _value = value;
                OnValueChanged(this, null);
                Invalidate();
            }
        }

        /// <summary>
        /// Get or set the minimal value. After setting the control will be invalidated.
        /// </summary>
        public double MinValue
        {
            get { return _minValue; }
            set
            {
                _minValue = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Get or set the maximal value. After setting the control will be invalidated.
        /// </summary>
        public double MaxValue
        {
            get { return _maxValue; }
            set
            {
                _maxValue = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gives back a triangle as a <see cref="GraphicsPath"/> which is
        /// directed down and dimensions of the passed Rectangle.
        /// </summary>
        /// <param name="paint"></param>
        /// <returns></returns>
        protected GraphicsPath GetSignUpPath(Rectangle paint)
        {
            GraphicsPath path = new GraphicsPath();

            // the middle from the triangle
            int selectorPoint = paint.Left + (paint.Width * (int)_value / (int)_maxValue);

            path.AddLines(new Point[]{new Point(selectorPoint, paint.Bottom-4),
                                      new Point(selectorPoint-5,paint.Bottom+1),
                                      new Point(selectorPoint-5, paint.Bottom+2),
                                      new Point(selectorPoint+5, paint.Bottom+2),
                                      new Point(selectorPoint+5, paint.Bottom+1)});
            path.CloseFigure();
            return path;
        }

        /// <summary>
        /// Gives back a triangle as a <see cref="GraphicsPath"/> which is
        /// directed top and dimensions of the passed Rectangle.
        /// </summary>
        /// <param name="paint"></param>
        /// <returns></returns>
        protected GraphicsPath GetSignDownPath(Rectangle paint)
        {
            GraphicsPath path = new GraphicsPath();
            int selectorPoint = paint.Left + (paint.Width * (int)_value / (int)_maxValue);

            path.AddLines(new Point[]{new Point(selectorPoint, paint.Top+4),
                                      new Point(selectorPoint-5,paint.Top-1),
                                      new Point(selectorPoint-5, paint.Top-2),
                                      new Point(selectorPoint+5, paint.Top-2),
                                      new Point(selectorPoint+5, paint.Top-1)});
            path.CloseFigure();
            return path;
        }

        #region Override Methods

        /// <summary>
        /// <b>Override:</b> When the padding is changed.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaddingChanged(EventArgs e)
        {
            base.OnPaddingChanged(e);
            Invalidate();
        }

        /// <summary>
        /// <b>Override:</b> When a Key is up.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left && Value> MinValue)
            {
                Value--;
            }
            else if (e.KeyCode == Keys.Right && Value < MaxValue)
            {
                Value++;
            }

            base.OnKeyUp(e);
        }

        #endregion

        #region Event

        /// <summary>
        /// Occures the event ValueChanged.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        protected virtual void OnValueChanged(object sender, EventArgs args)
        {
            if (ValueChanged != null)
            {
                ValueChanged(sender, args);
            }
        }

        #endregion
    }
}
